package ru.ifmo.itmokis.util;

import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.NoResultException;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import ru.ifmo.itmokis.domain.*;

/**
 *
 * @author Ivan Stepuk
 */
public class DataContext {

    private EntityManager manager;

    public DataContext(EntityManager manager) {
        this.manager = manager;
    }

    public List<OrderedProduct> history(Time from, Time to) {
        String qs = "SELECT op FROM OrderedProduct op "
                + "WHERE op.startTime >= :from AND op.finishTime <= :to";
        TypedQuery<OrderedProduct> query = manager.createQuery(qs, OrderedProduct.class);
        query.setParameter("from", from);
        query.setParameter("to", to);
        return query.getResultList();
    }

    public int countOrdersByStatus(Order.Status status) {
        String qs = "SELECT COUNT(o.id) FROM Order1 o WHERE o.status = :status";
        Query query = manager.createQuery(qs);
        query.setParameter("status", status);
        Number res = null;
        try {
            res = (Number) query.getSingleResult();
        } catch (NoResultException ex) {
            res = new Integer(0);
        } finally {
            return res.intValue();
        }
    }

    public User getUserById(int id) {
        return manager.find(User.class, id);
    }

    public Product getProductByName(String name) {
        String qs = "SELECT p FROM Product p WHERE p.name = :name";
        TypedQuery<Product> query = manager.createQuery(qs, Product.class);
        query.setParameter("name", name);
        return query.getSingleResult();
    }

    public Material getMaterialByName(String name) {
        String qs = "SELECT m FROM Material m WHERE m.name = :name";
        TypedQuery<Material> query = manager.createQuery(qs, Material.class);
        query.setParameter("name", name);
        return query.getSingleResult();
    }

    public void updateMaterialQty(Material material, int delta) {
        EntityTransaction transaction = manager.getTransaction();
        transaction.begin();
        Material m = manager.find(Material.class, material.getId());
        m.setQty(m.getQty() + delta);
        transaction.commit();
    }

    public void persist(Object object) {
        EntityTransaction transaction = manager.getTransaction();
        transaction.begin();
        manager.persist(object);
        transaction.commit();
    }

    public Order getOrderById(int id) {
        return manager.find(Order.class, id);
    }

    public void advanceOrder(Order order) {
        EntityTransaction transaction = manager.getTransaction();
        transaction.begin();
        Order o = manager.find(Order.class, order.getId());
        o.setCompletedProducts(o.getCompletedProducts() + 1);
        transaction.commit();
    }

    public void setOrderCompleted(Order order, Time when) {
        EntityTransaction transaction = manager.getTransaction();
        transaction.begin();
        Order o = manager.find(Order.class, order.getId());
        o.setCompletionTime(when);
        o.setStatus(Order.Status.COMPLETED);
        transaction.commit();
    }

    public void updateOrderStatus(Order order, Order.Status status) {
        EntityTransaction transaction = manager.getTransaction();
        transaction.begin();
        Order o = manager.find(Order.class, order.getId());
        o.setStatus(status);
        transaction.commit();
    }

    public void updateOrderDeadline(Order order, Time deadline) {
        EntityTransaction transaction = manager.getTransaction();
        transaction.begin();
        Order o = manager.find(Order.class, order.getId());
        o.setDeadline(deadline);
        transaction.commit();
    }

    public List<Supply> getSuppliesByOrderTime(Time orderTime) {
        String qs = "SELECT s FROM Supply s WHERE s.orderTime = :time";
        TypedQuery<Supply> query = manager.createQuery(qs, Supply.class);
        query.setParameter("time", orderTime.toPlainHours());
        return query.getResultList();
    }

    public List<Supply> getUndeliveredSupplies() {
        String qs = "SELECT s FROM Supply s WHERE s.deliveryTime IS NULL";
        TypedQuery<Supply> query = manager.createQuery(qs, Supply.class);
        return query.getResultList();
    }

    public void updateSupplyDeliveryTime(Supply supply, Time deliveryTime) {
        EntityTransaction transaction = manager.getTransaction();
        transaction.begin();
        Supply s = manager.find(Supply.class, supply.getId());
        s.setDeliveryTime(deliveryTime);
        transaction.commit();
    }
}
